﻿# +---------------------------------------------------------------------------
# | File : Deployment_Test.ps1                                          
# | Version : 1.00                                          
# | Purpose : Controller script for application deployment
# | Synopsis: 
# +---------------------------------------------------------------------------
# | Maintenance History                                            
# | -------------------                                            
# | Name            Date         Version     Description        
# | -------------------------------------------------------------------------- 
# | Brian Sykes     05-14-2014   1.00        Creation
# +---------------------------------------------------------------------------


function Deploy
{

[cmdletbinding()]
Param(
[Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()]
[string] $SrcDir,
[Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()]
[string] $Environment,
[Parameter()] [ValidateSet($true,$false)]
[string] $EchoHost = $false
)
    
    $global:LOGFILE_PATH = $SrcDir + "\_DeploymentLogs\" + $Environment + "_Deployment_" + (Get-Date -Format yyyyMMddHHmmss) + ".txt"

    # Import CommonFunctions module
    $commonFunctionsModulePath = "C:\CodePlex\psdeploymentautomation\Modules\CommonFunctions.psm1"
    Import-Module $commonFunctionsModulePath -Force

    #Trim variable value of the staging path
    $SrcDir = $SrcDir.Trim().TrimEnd("\")
    
    # create global variables from input parameters
    $global:SRC_DIR = $SrcDir
    $global:ENV = $Environment

    # Create Paths to Server Lists
    $global:APP_SERVERS = "C:\CodePlex\psdeploymentautomation\Scripts\" + $ENV + "_Deploy\App_Servers.txt"
    $global:WEB_SERVERS = "C:\CodePlex\psdeploymentautomation\Scripts\" + $ENV + "_Deploy\Web_Servers.txt"

    # Import Paths.csv file containing the deployment details
    $pathsCsv = "C:\CodePlex\psdeploymentautomation\Scripts\" + $ENV + "_Deploy\Paths.csv"
    $global:PATHS = Import-Csv -Path $pathsCsv

    Write-Log -Path $LOGFILE_PATH -EchoHost $EchoHost -Message "Source folder = $SrcDir" 
    Write-Log -Path $LOGFILE_PATH -EchoHost $EchoHost -Message "Selected environment = $Env"

    try
    {
        Backup-Files
        Publish-Files

        Write-Log -Path $LOGFILE_PATH -EchoHost $EchoHost -Message "Deployment to $ENV is complete"
    }
    catch [exception]
    {
        $failMessage = "$($_.Exception.ToString()). $($_.InvocationInfo.PositionMessage)"
        Write-Log -Path $LOGFILE_PATH -EchoHost $EchoHost -Message $failMessage
    }
}



function Backup-Files
{
    # Get current date/time for backup folder name
    $currentDateTime= get-date -format MMddyyyyhhmm

    # Iterate through the $PATHS object derived from the .csv 
    foreach($path in $PATHS)
    {
        #get current server role (App/Web/etc.) for this iteration 
        $role = $path.ROLE     

        # get server list based on $role
        switch ($role)
        {
            "App" { $servers = Get-Content $APP_SERVERS }
            "Web" { $servers = Get-Content $WEB_SERVERS }
        }

        # Backup source == deployment target
        $backupSource = $path.TARGET

        # get folder name from backup source
        $folderName = Split-Path $backupSource -Leaf

        # create path string for backup destination folder 
        $baseBackupDestination = "c$\Backup\backup.$currentDateTime\"
        $backupDestination = $baseBackupDestination + $folderName
        
        # Iterate through server list
        foreach($server in $servers)
        {
            Write-Log -Path $LOGFILE_PATH -EchoHost $EchoHost -Message "Backing up files from \\$server\$backupSource to \\$server\$backupDestination"
            

            #call our Backup function from CommonFunctions module
            $result = Backup -Source $backupSource -Destination $backupDestination -Server $server

            # Backup function returned "SUCCESS":
            if ($result -eq "SUCCESS")
            {
                # Celebrate good times
                Write-Log -Path $LOGFILE_PATH -EchoHost $EchoHost -Message "SUCCESS!"
            }
            else
            {
                # uh oh! 
                throw $result + "`nBACKUP FAILED"
            }
        }
    }
}


function Publish-Files
{
    # Iterate through the $PATHS object derived from the .csv 
    foreach($path in $PATHS)
    {
        #create variables for Source, Target, and Role of current iteration
        $source = $SRC_DIR + $path.SOURCE
        $target = $path.TARGET
        $role = $path.ROLE

        # get server list based on $role
        switch ($role)
        {
            "App" { $servers = Get-Content $APP_SERVERS }
            "Web" { $servers = Get-Content $WEB_SERVERS }
        }
        
        # Iterate through server list
        foreach($server in $servers)
        {
            Write-Log -Path $LOGFILE_PATH -EchoHost $EchoHost -Message "Publishing files from $source to $target on $server"

            #call Publish function from CommonFunctions module
            $result = Publish -SourceFiles $source -Destination $target -Server $server

            # Publish function returned "SUCCESS"
            if ($result -eq "SUCCESS")
            {
                # It worked!!
                Write-Log -Path $LOGFILE_PATH -EchoHost $EchoHost -Message "SUCCESS!"

            }
            else
            {
                # Dang.
                throw $result + "`nPUBLISH FAILED"
            }
        }
    }
}



function Save-ServiceStates
{
    
[cmdletbinding()]
Param(
[Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()]
[string]$ServerList,
[Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()]
[string]$ServiceAccount,
[Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()]
[string]$ServiceStatesFile
)

    if(-not(Test-Path $ServiceStatesFile))
    {
        #create csv header for services array stored file
        '"Computername","Name","State","Startmode"' | out-file $ServiceStatesFile -Force
    }
    else
    {
        Write-Log -Path $PATH_TO_LOG_FILE "Services Array File: $ServiceStatesFile already exists!! Creating a backup copy before overwriting original..."
        $currentDateTime= get-date -format MMddyyyyhhmm
        $fileCopy = $ServiceStatesFile.TrimEnd(".txt") + "_" + $currentDateTime + ".txt"
        Copy-Item $ServiceStatesFile $fileCopy -Force
        Write-Log -Path $PATH_TO_LOG_FILE "Created: $fileCopy"

        #overwrite prior Service States File with new header...
        '"Computername","Name","State","Startmode"' | out-file $ServiceStatesFile -Force
    }
    
	# Get content from server list file to create $servers array
	$servers = get-content $ServerList
    try
    {
        foreach($server in $servers)
        {
            $server = $server.trim()
            $tempMsg = "Getting current application service states on " + $server
            Write-Log -Path $PATH_TO_LOG_FILE "Getting current application service states on $server"

            # Call Get-ServiceAttributes function
            $services = Get-ServiceAttributes -server $server -serviceAccount $ServiceAccount

			foreach ($service in $services)
			{
				$serviceName = $service.name
				$serviceState = $service.State
				$serviceStartMode = $service.StartMode
				Write-Log -Path $PATH_TO_LOG_FILE $server 
				Write-Log -Path $PATH_TO_LOG_FILE $service.name 
				Write-Log -Path $PATH_TO_LOG_FILE $service.State 
				Write-Log -Path $PATH_TO_LOG_FILE $service.StartMode 
			
				$servicesCSVLine = "`"$server`",`"$serviceName`",`"$serviceState`",`"$serviceStartMode`""
				$servicesCSVLine | out-file $ServiceStatesFile -append	
			}
        }
    }
    catch [exception]
    {
        $failMessage = "$($_.Exception.ToString()). $($_.InvocationInfo.PositionMessage)" + "`nSaving Service States failed"
        Write-Log -Path $PATH_TO_LOG_FILE $failMessage 
        throw $failMessage
    }

    Write-Log -Path $PATH_TO_LOG_FILE "Service states were successfully saved to file"
}